package repositories

import (
	"gitee.com/golanglearn/small/database"
	"gitee.com/golanglearn/small/models"
)

type ThemeRepository interface {
	Create(p *models.Theme) error
	GetAll() ([]*models.Theme, error)
	FindById(id int) (*models.Theme, error)
	Delete(id int) error
	Paginate(perpage int, offset int) ([]*models.Theme, error)
	GetTotalThemeCount() (int, error)
}

type themeRepository struct {
	*database.MySQLDB
}

func NewThemeRepository(db *database.MySQLDB) ThemeRepository {
	return &themeRepository{db}
}

func (tr *themeRepository) Create(t *models.Theme) error {

	stmt, err := tr.DB.Prepare("INSERT INTO theme SET name=?, u_id=?, descinfo=?, created_at=?")
	if err != nil {
		return err
	}
	defer stmt.Close()
	result, err := stmt.Exec(t.Name, t.UID, t.Descinfo, t.CreatedAt.Format("20060102150405"))
	if err != nil {
		return err
	}

	tId, err := result.LastInsertId()
	if err != nil {
		return err
	}
	t.ID = int(tId)

	return nil
}

func (tr *themeRepository) GetAll() ([]*models.Theme, error) {
	var themes []*models.Theme

	rows, err := tr.DB.Query("SELECT t.id, t.name, u.name author, t.descinfo, t.created_at, t.updated_at from theme t INNER JOIN users u ON t.u_id = u.id")
	if err != nil {
		return nil, err
	}
	defer rows.Close()

	for rows.Next() {
		t := new(models.Theme)
		err := rows.Scan(&t.ID, &t.Name, &t.Author, &t.Descinfo, &t.CreatedAt, &t.UpdatedAt)
		if err != nil {
			return nil, err
		}
		themes = append(themes, t)
	}

	if err := rows.Err(); err != nil {
		return nil, err
	}

	return themes, nil
}

func (tr *themeRepository) GetTotalThemeCount() (int, error) {
	var count int
	err := tr.DB.QueryRow("SELECT COUNT(*) FROM theme").Scan(&count)
	if err != nil {
		return -1, err
	}

	return count, nil
}

func (tr *themeRepository) Paginate(perpage int, offset int) ([]*models.Theme, error) {
	var themes []*models.Theme

	rows, err := tr.DB.Query("SELECT t.id, t.name, u.name author, t.descinfo, t.created_at, t.updated_at from theme t INNER JOIN users u ON t.u_id = u.id LIMIT ? OFFSET ?", perpage, offset)
	if err != nil {
		return nil, err
	}
	defer rows.Close()

	for rows.Next() {
		t := new(models.Theme)
		err := rows.Scan(&t.ID, &t.Name, &t.Author, &t.Descinfo, &t.CreatedAt, &t.UpdatedAt)
		if err != nil {
			return nil, err
		}
		themes = append(themes, t)
	}

	if err := rows.Err(); err != nil {
		return nil, err
	}

	return themes, nil
}

func (tr *themeRepository) FindById(id int) (*models.Theme, error) {
	theme := models.Theme{}

	err := tr.DB.QueryRow("SELECT t.id, t.name, t.u_id, u.name author, t.descinfo, t.created_at, t.updated_at from theme t INNER JOIN users u ON t.u_id = u.id WHERE t.id = ?", id).Scan(&theme.ID, &theme.Name, &theme.UID, &theme.Author, &theme.Descinfo, &theme.CreatedAt, &theme.UpdatedAt)
	if err != nil {
		return nil, err
	}

	return &theme, nil
}

func (tr *themeRepository) Delete(id int) error {
	stmt, err := tr.DB.Prepare("DELETE FROM theme WHERE id = ?")
	if err != nil {
		return err
	}
	defer stmt.Close()
	_, err = stmt.Exec(id)
	if err != nil {
		return err
	}

	return nil
}
